﻿using System;
using System.ComponentModel;
using Borg.Properties;

namespace Borg
{
    public abstract class SettingCollection : ISettingContainer
    {
        private bool _isMultiUpdate;
        private bool _isCollectionChanged;

        public event EventHandler CollectionChanged;

        internal ISettingContainer Parent { get; set; }

        internal SettingStore SettingStore
        {
            get
            {
                var settingCollection = Parent as SettingCollection;

                if (settingCollection != null)
                    return settingCollection.SettingStore;

                var settingStore = Parent as SettingStore;

                if (settingStore != null)
                    return settingStore;
                
                if (Parent == null)
                    return null;
                
                throw new InvalidOperationException();
            }
        }

        public void BeginUpdate()
        {
            _isMultiUpdate = true;
        }

        public void EndUpdate()
        {
            _isMultiUpdate = false;

            if (!_isCollectionChanged)
                return;

            _isCollectionChanged = false;

            OnCollectionChanged();
        }

        protected internal virtual void OnCollectionChanged()
        {
            if (_isMultiUpdate)
                _isCollectionChanged = true;
            else
            {
                if (CollectionChanged == null)
                    return;

                CollectionChanged(this, EventArgs.Empty);
            }
        }

        internal static string ConvertToString<T>(T value)
        {
            var converter = TypeDescriptor.GetConverter(typeof(T));

            if (converter == null)
                throw new InvalidOperationException(
                    string.Format(Exceptions.No_converter_found, typeof(T).Name));
            
            return converter.ConvertToInvariantString(value);
        }

        internal static T ConvertFromString<T>(string value)
        {
            var converter = TypeDescriptor.GetConverter(typeof(T));

            if (converter == null)
                throw new InvalidOperationException(
                    string.Format(Exceptions.No_converter_found, typeof(T).Name));
            
            return (T)converter.ConvertFromInvariantString(value);
        }
    }
}
